package com.atguigu.mybatisplus.common.aop;

import com.atguigu.mybatisplus.common.annotation.Log;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
public class SysAspect {

    @Pointcut("@annotation(com.atguigu.mybatisplus.common.annotation.Log)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // ========== 1. 获取方法签名信息 ==========
        // 获取连接点的方法签名对象
        Signature signature = joinPoint.getSignature();
        // 转换为方法签名专有对象（可以获取更多方法信息）
        MethodSignature methodSignature = (MethodSignature) signature;

        // 通过方法签名获取当前执行的目标方法对象
        Method method = methodSignature.getMethod();

        // ========== 2. 处理自定义注解 ==========
        // 检查方法是否存在（防御性编程）
        if (method != null) {
            // 获取方法上的@Log注解实例
            Log log = method.getAnnotation(Log.class);
            // 输出注解的name属性值（这里可能NPE，如果方法没有@Log注解）
            System.out.println(log.name());
        }

        // ========== 3. 获取方法基本信息 ==========
        // 获取当前执行的方法名称
        String name = method.getName();
        System.out.println(name);

        // ========== 4. 获取HTTP请求信息 ==========
        // 获取当前请求的属性对象（需要Spring Web环境）
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 转换为Servlet专有请求属性对象（包含HTTP请求信息）
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        // 获取HttpServletRequest对象
        HttpServletRequest request = servletRequestAttributes.getRequest();

        // 获取请求URL
        String url = request.getRequestURI().toString();
        System.out.println(url);

        // 获取HTTP方法（GET/POST等）
        String methodName = request.getMethod();
        System.out.println(methodName);

        // 获取客户端IP地址
        String ipAddr = request.getRemoteAddr();
        System.out.println(ipAddr);

        // ========== 5. 其他处理 ==========
        // 输出当前时间
        System.out.println(LocalDateTime.now());

        // ========== 6. 执行目标方法 ==========
        // 关键点：调用proceed()才会执行被拦截的实际方法
        // 可以在此前做前置处理，在此后做后置处理
        return joinPoint.proceed();
    }
}
